package com.dz.risk.service.impl;

import com.dz.risk.exception.VerifyException;
import com.dz.risk.pojo.domain.ReportFormsEntity;
import com.dz.risk.pojo.model.FormulaModel;
import com.dz.risk.service.FormulaCalculationService;
import com.dz.risk.service.ReportFormsDataValueService;
import com.dz.risk.service.ReportFormsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

/**
 * 公式计算业务处理类
 *
 * @author Doke
 * @date 2021/8/2 10:57
 */
@Service
public class FormulaCalculationServiceImpl implements FormulaCalculationService {

    /**
     * 混合运算
     */
    private static final String MIXED_COMPUTING = "1";

    /**
     * sql运算
     */
    private static final String SQL_OPERATION = "2";

    /**
     * 大小判断(大大取大,小小取小)
     */
    private static final String SIZE_JUDGMENT = "3";

    /**
     * 公式计算操作对象
     */
    private static final ExpressionParser PARSER = new SpelExpressionParser();

    private final ReportFormsDataValueService reportFormsDataValueService;

    private final ReportFormsService reportFormsService;

    @Autowired
    public FormulaCalculationServiceImpl(ReportFormsDataValueService reportFormsDataValueService, ReportFormsService reportFormsService) {
        this.reportFormsDataValueService = reportFormsDataValueService;
        this.reportFormsService = reportFormsService;
    }

    /**
     * 根据公式对象计算公式值
     *
     * @param cellSerialNumber 单元格编号
     * @param formulaModel  公式模型
     * @param versionBeginDate 版本开始时间
     * @param versionEndDate   版本结束时间
     * @return 公式最终计算值
     */
    @Override
    public String calculateTheValueBasedOnTheFormulaObject(String cellSerialNumber, FormulaModel formulaModel, Date versionBeginDate, Date versionEndDate) {
        Assert.notNull(formulaModel, "公式对象不能为空");

        String dataValue = null;

        /*//公式类型
        String formulaType = cellFormatModel.getFormulaType();

        //判断公式是否为混合运算
        if (MIXED_COMPUTING.equals(formulaType)) {
            //混合运算
            dataValue = mixedComputing(cellFormatModel.getFormula(), cellFormatModel.getParseFormula(), versionBeginDate, versionEndDate);

            //判断公式是否为sql运算
        } else if (SQL_OPERATION.equals(formulaType)) {

            //判断公式是否为大小判断运算
        } else if (SIZE_JUDGMENT.equals(formulaType)) {


        } else {
            throw new VerifyException(versionBeginDate + "~" + versionEndDate + "版本的单元格M{" + cellSerialNumber + "}公式类型错误,请调整");
        }*/


        return dataValue;
    }

    /**
     * 混合运算
     *
     * @param formula          公式
     * @param parseFormula     参与计算的单元格编号集合
     * @param versionBeginDate 参数版本开始时间
     * @param versionEndDate   参数版本结束时间
     * @return 计算值
     */
    private String mixedComputing(String formula, List<String> parseFormula, Date versionBeginDate, Date versionEndDate) {

        //公式值
        String formulaValue = null;

        //遍历参与公式计算的单元格集合获取所有参与的单元格对应值并对公式进行替换
        parseFormula.forEach(a -> {

            //判断该单元格是否需要计算(末位为0才参与计算)


            //根据单元格编号以及版本获取最新的该单元格数据
            String cellDataValue = getCellDataValueByTableCellSerialNumberAndVersion(a, versionBeginDate, versionEndDate);

            //如果该单元格已经有数据值则直接替换到公式中使用
            formula.replace(a, cellDataValue);


        });

        return (String) PARSER.parseExpression(formula).getValue();
    }

    /**
     * 根据单元格编号以及版本区间时间获取最新的单元格数据
     *
     * @param cellSerialNumber 单元格编号
     * @param versionBeginDate 版本开始时间
     * @param versionEndDate   版本结束时间
     * @return 单元格最终值
     */
    private String getCellDataValueByTableCellSerialNumberAndVersion(String cellSerialNumber, Date versionBeginDate, Date versionEndDate) {

        //根据单元格编号以及版本区间获取该区间版本的该单元格所属的报表基本信息
        List<ReportFormsEntity> reportFormsEntities = reportFormsService.selectByCellSerialNumberAndBeginDateAndEndDate(cellSerialNumber, versionBeginDate, versionEndDate);

        //如果该报表版本还未生成则提示无法计算
        if (CollectionUtils.isEmpty(reportFormsEntities)) {
            throw new VerifyException(versionBeginDate + "~" + versionEndDate + "的M{" + cellSerialNumber + "}单元格模板还未导入,无法进行引用计算");
        }


        return null;
    }
}
